use std::cell::RefCell;
use std::rc::Rc;
use crate::misc::shape_to_strides;
use crate::Tensor;
use crate::tensor::TensorCell;

impl<T> From<(Rc<Box<[T]>>, Box<[usize]>)> for Tensor<T> {
    fn from(params: (Rc<Box<[T]>>, Box<[usize]>)) -> Self {
        (params.0, 0, params.1.clone(), shape_to_strides(params.1.as_ref())).into()
    }
}

impl<T> From<(Rc<Box<[T]>>, usize, Box<[usize]>, Box<[usize]>)> for Tensor<T> {
    fn from(params: (Rc<Box<[T]>>, usize, Box<[usize]>, Box<[usize]>)) -> Self {
        Tensor {
            ptr: Rc::new(RefCell::new(TensorCell {
                data: params.0,
                offset: params.1,
                shape: params.2,
                strides: params.3,
                grad: None,
                grad_fn: None,
                retains_grad: false,
                requires_grad: false,
            })),
        }
    }
}

impl<T> From<Vec<T>> for Tensor<T> {
    fn from(data: Vec<T>) -> Self {
        let len = data.len();
        (data.into_boxed_slice().into(), 0, [len].into(), [1].into()).into()
    }
}

impl<T> From<(Vec<T>, Vec<usize>)> for Tensor<T> {
    fn from(params: (Vec<T>, Vec<usize>)) -> Self {
        (Rc::new(params.0.into()), 0, params.1.into_boxed_slice(), [1].into()).into()
    }
}
